 /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package test.shanika;

import com.googlecode.javacv.cpp.opencv_calib3d.*;
import com.googlecode.javacv.FrameGrabber.Exception;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.googlecode.javacv.cpp.opencv_core.*;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.opencv_calib3d.*;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import objectExtraction.HSVSkinDetector;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;

/**
 *
 * @author HOME
 */
public class FinalBackie {

// Global storage
    IplImage IavgF, IdiffF, IprevF, IhiF, IlowF;
    IplImage Iscratch, Iscratch2;
    IplImage Igray1, Igray2, Igray3;
    IplImage Ilow1, Ilow2, Ilow3;
    IplImage Ihi1, Ihi2, Ihi3;
    IplImage Imaskt;
    float Icount;
    public static int first = 1;
// Function of allocating images

    public void AllocateImages(IplImage I) {

        CvSize sz = I.cvSize();

        IavgF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        IdiffF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        IprevF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        IhiF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        IlowF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        Ilow1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Ilow2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Ilow3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Ihi1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Ihi2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Ihi3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);

        cvZero(IavgF);
        cvZero(IdiffF);
        cvZero(IprevF);
        cvZero(IhiF);
        cvZero(IlowF);
        // protect against divid by 0
        Icount = (float) 0.0001;


        Iscratch = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        Iscratch2 = cvCreateImage(sz, IPL_DEPTH_32F, 3);
        Igray1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Igray2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Igray3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
        Imaskt = cvCreateImage(sz, IPL_DEPTH_8U, 1);
        cvZero(Iscratch);
        cvZero(Iscratch2);
    }

    // Learn the background statistics for one more frame
    public void accumulateBackground(IplImage I) {
        cvCvtScale(I, Iscratch, 1, 0);
        if (first == 0) {
            cvAcc(Iscratch, IavgF, null);
            cvAbsDiff(Iscratch, IprevF, Iscratch2);
            cvAcc(Iscratch2, IdiffF, null);
            Icount += 1.0;
        }
        first = 0;
        cvCopy(Iscratch, IprevF);
    }

    void setHighThreshold(float scale) {
        cvConvertScale(IdiffF, Iscratch, scale, 0);
        cvAdd(Iscratch, IavgF, IhiF, null);
        cvSplit(IhiF, Ihi1, Ihi2, Ihi3, null);
    }

    void setLowThreshold(float scale) {
        cvConvertScale(IdiffF, Iscratch, scale, 0);
        cvAdd(Iscratch, IavgF, IlowF, null);
        cvSplit(IlowF, Ilow1, Ilow2, Ilow3, null);
    }

    void createModelsfromStats() {
        CanvasFrame can=new CanvasFrame("Show");
        cvConvertScale(IavgF, IavgF, (double) (1.0 / Icount), 0);
        cvConvertScale(IdiffF, IdiffF, (double) (1.0 / Icount), 0);
     

        //Make sure diff is always something
        cvAddS(IdiffF, cvScalar(1.0, 1.0, 1.0, 0), IdiffF, null);
       
        this.setHighThreshold((float) 7.0);
        this.setLowThreshold((float) 6.0);
    }

    // Create a mask
    void backgroundDiff(IplImage I, IplImage Imask) {
        cvCvtScale(I, Iscratch, 1, 0);
        cvSplit(Iscratch, Igray1, Igray2, Igray3, null);

        // channel 1
        cvInRange(Igray1, Ilow1, Ihi1, Imask);
        // channel 2
        cvInRange(Igray2, Ilow2, Ihi2, Imaskt);
        cvOr(Imask, Imaskt, Imask, null);
        // channel 3
        cvInRange(Igray3, Ilow3, Ihi3, Imaskt);
        cvOr(Imask, Imaskt, Imask, null);
    }

    void DeallocateImages() {
        cvReleaseImage(IavgF);
        cvReleaseImage(IdiffF);
        cvReleaseImage(IprevF);
        cvReleaseImage(IhiF);
        cvReleaseImage(IlowF);
        cvReleaseImage(Ilow1);
        cvReleaseImage(Ilow2);
        cvReleaseImage(Ilow3);
        cvReleaseImage(Ihi1);
        cvReleaseImage(Ihi2);
        cvReleaseImage(Ihi3);
        cvReleaseImage(Iscratch);
        cvReleaseImage(Iscratch2);
        cvReleaseImage(Igray1);
        cvReleaseImage(Igray2);
        cvReleaseImage(Igray3);
        cvReleaseImage(Imaskt);
    }

    public static void main(String[] args) {
        try {
            FrameGrabber grabber = new VideoInputFrameGrabber(0);
            CanvasFrame fg = new CanvasFrame("Foreground");
            CanvasFrame bg = new CanvasFrame("Background");
            CanvasFrame th = new CanvasFrame("Threshold Image");
            FinalBackie fb = new FinalBackie();
            HSVSkinDetector hs = new HSVSkinDetector();


            IplImage frame, mask1, mask3;
            int frameCount = 0;
            grabber.start();
            Thread.sleep(1000);
            while (true) {
                frameCount++;
                frame = grabber.grab();
                
                if (frame == null) {
                    break;
                }
                CvSize sz = cvGetSize(frame);
                mask1 = cvCreateImage(sz, IPL_DEPTH_8U, 1);
                mask3 = cvCreateImage(sz, IPL_DEPTH_8U, 3);

                if (frameCount == 1) {
                    System.out.println("Please wait");
                    fb.AllocateImages(frame);
                }
                if (frameCount < 30) {
                    System.out.println("Please wait");
                    fb.accumulateBackground(frame);
                } else if (frameCount == 30) {
                    fb.createModelsfromStats();
                } else {
                    fb.backgroundDiff(frame, mask1);
                    bg.showImage(mask1);
                    cvCvtColor(mask1, mask3, CV_GRAY2BGR);
                    cvNorm(mask3, mask3, CV_C, null);
                    cvThreshold(mask3, mask3, 100, 1, CV_THRESH_BINARY);
                    cvMul(frame, mask3, frame, 1.0);
                    fg.showImage(frame);
                    IplImage skin = hs.getHSVSkin(frame);
                    th.showImage(skin);
                }
            }


        } catch (InterruptedException ex) {
            Logger.getLogger(FinalBackie.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(FinalBackie.class.getName()).log(Level.SEVERE, null, ex);
        }



    }
}
